<template>
  <div class="card-table">
    <!-- 加载状态 -->
    <div v-if="loading">加载中...</div>

    <!-- 空状态 -->
    <div v-else-if="!data || data.length === 0" class="empty-state">
      <el-empty description="暂无数据"></el-empty>
    </div>

    <!-- 卡片列表 -->
    <div v-else class="card-list" :class="{ 'striped': stripe }">
      <div
        v-for="(item, index) in data"
        :key="getRowKey(item, index)"
        class="card-item"
        :style="{ 'border-radius': borderRadius + 'px' }"
      >
        <!-- 卡片头部 -->
        <div v-if="$slots.header" class="card-header">
          <slot name="header" :row="item" :index="index"></slot>
        </div>

        <!-- 卡片内容 -->
        <div class="card-content">
          <!-- 复选框列 -->
          <div v-if="showCheckbox" class="checkbox-column">
            <el-checkbox
              v-model="checkedRowKeys"
              :label="getRowKey(item, index)"
              :disabled="isRowDisabled(item) || !isSelectable(item)"
              @change="handleRowSelectionChange"
            ></el-checkbox>
          </div>

          <!-- 数据列 -->
          <div v-for="column in columnsConfig" :key="column.prop || column.label || column.key" class="card-column">
            <div class="column-label">{{ column.label }}</div>
            <div
              class="column-value"
              :class="{ 'ellipsis': column.showOverflowTooltip }"
            >
              <!-- 处理自定义插槽内容 -->
              <template v-if="column.hasCustomSlot">
                <component :is="renderCustomSlot(column, item, index)" />
              </template>
              <!-- 处理普通内容 -->
              <template v-else>
                {{ getColumnValue(item, column) }}
              </template>
            </div>
          </div>
        </div>

        <!-- 卡片尾部 -->
        <div v-if="$slots.footer" class="card-footer">
          <slot name="footer" :row="item" :index="index"></slot>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
  import { ref, computed, onMounted, watch, nextTick } from 'vue'
  import { ElCheckbox, ElEmpty } from 'element-plus'

  // Props
  const props = defineProps({
    data: {
      type: Array,
      default: () => []
    },
    columns: {
      type: Array,
      default: () => []
    },
    stripe: {
      type: Boolean,
      default: false
    },
    loading: {
      type: Boolean,
      default: false
    },
    rowKey: {
      type: [String, Function],
      default: 'id'
    },
    border: {
      type: Boolean,
      default: true
    },
    borderRadius: {
      type: Number,
      default: 6
    },
    showCheckbox: {
      type: Boolean,
      default: false
    },
    selectable: {
      type: Function,
      default: () => true
    },
    disabled: {
      type: Function,
      default: () => false
    }
  })

  // Emits
  const emit = defineEmits(['selection-change', 'row-click'])

  // Slots
  const slots = useSlots()

  // 内部状态
  const columnsConfig = ref([])
  const checkedRowKeys = ref([]) // 存储选中的行的key
  const loadingElement = ref(null)
  const customSlotContentMap = ref(new Map()) // 存储自定义插槽内容

  // 计算选中的行数据
  const selectedRows = computed(() => {
    return props.data.filter(item =>
      checkedRowKeys.value.includes(getRowKey(item))
    )
  })

  // 获取行唯一标识
  function getRowKey(row, index) {
    if (typeof props.rowKey === 'function') {
      return props.rowKey(row, index)
    } else if (typeof row[props.rowKey] !== 'undefined') {
      return row[props.rowKey]
    }
    return index
  }

  // 获取列值，支持嵌套属性
  function getColumnValue(row, column) {
    if (column.formatter && typeof column.formatter === 'function') {
      return column.formatter(row, column)
    }

    if (!column.prop) return ''

    // 处理嵌套属性，如 'user.name'
    const keys = column.prop.split('.')
    let value = row

    for (const key of keys) {
      if (value === null || value === undefined) {
        return ''
      }
      value = value[key]
    }

    return value === null || value === undefined ? '' : value
  }

  // 解析表格列配置
  function parseTableColumns() {
    try {
      // 优先使用columns属性
      if (props.columns && props.columns.length > 0) {
        columnsConfig.value = props.columns
        return
      }

      // 从插槽中解析列配置
      let slotContent = slots.default?.() || []
      if (slotContent[0] && typeof slotContent[0].type === 'symbol') {
        slotContent = slotContent[0].children || [];
      }
      const tableColumns = slotContent.filter(vnode => {
        // 检查是否为el-table-column组件
        return vnode.type?.name === 'ElTableColumn' ||
          vnode.type?.__name === 'ElTableColumn';
      });

      const newColumnsConfig = tableColumns.map((col, columnIndex) => {
        const { props: colProps, children } = col
        if (!colProps) return null

        // 检查是否有自定义插槽内容
        const hasCustomSlot = children && (children.default || Object.keys(children).length > 0)
        const slotKey = colProps.prop || `slot-${columnIndex}`

        // 存储自定义插槽内容
        if (hasCustomSlot && children) {
          customSlotContentMap.value.set(slotKey, children)
        }

        return {
          prop: colProps.prop,
          label: colProps.label,
          formatter: colProps.formatter,
          width: colProps.width,
          minWidth: colProps.minWidth,
          align: colProps.align,
          showOverflowTooltip: colProps.showOverflowTooltip,
          key: colProps.key,
          hasCustomSlot: hasCustomSlot,
          slotKey: slotKey
        }
      }).filter(Boolean)

      // 只有当列配置发生变化时才更新
      if (JSON.stringify(newColumnsConfig) !== JSON.stringify(columnsConfig.value)) {
        columnsConfig.value = newColumnsConfig
      }
    } catch (error) {
      console.error('解析表格列配置时出错:', error)
    }
  }

  // 渲染自定义插槽内容
  function renderCustomSlot(column, row, index) {
    const slotContent = customSlotContentMap.value.get(column.slotKey)
    if (!slotContent) {
      return () => h('span', getColumnValue(row, column))
    }

    // 创建一个组件来渲染插槽内容
    return {
      render() {
        try {
          // 处理默认插槽
          if (typeof slotContent.default === 'function') {
            return slotContent.default({
              row: row,
              $index: index,
              column: column
            })
          }
          // 处理命名插槽（如果有）
          else if (typeof slotContent.default === 'object') {
            return slotContent.default
          }
          return h('span', getColumnValue(row, column))
        } catch (error) {
          console.error('渲染自定义插槽时出错:', error)
          return h('span', getColumnValue(row, column))
        }
      }
    }
  }

  // 处理行选择变化
  function handleRowSelectionChange() {
    // 发射selection-change事件，传递选中的行数据
    emit('selection-change', selectedRows.value)
  }

  // 检查行是否可选择
  function isSelectable(row) {
    return props.selectable && props.selectable(row)
  }

  // 检查行是否可禁用
  function isRowDisabled(row) {
    return props.disabled && props.disabled(row)
  }

  // 监听数据变化
  watch(() => props.data, () => {
    parseTableColumns()
    // 数据变化时，过滤掉不再存在的行的选中状态
    checkedRowKeys.value = checkedRowKeys.value.filter(key =>
      props.data.some(item => getRowKey(item) === key)
    )
  }, { deep: true, immediate: true })

  // 监听columns变化
  watch(() => props.columns, () => {
    parseTableColumns()
  }, { deep: true })

  // 监听showCheckbox变化，清空选择
  watch(() => props.showCheckbox, (newVal, oldVal) => {
    if (newVal !== oldVal) {
      checkedRowKeys.value = []
    }
  })

  // 组件挂载时解析列配置
  onMounted(() => {
    nextTick(() => {
      parseTableColumns()
    })
  })
</script>

<style scoped>
  .card-table {
    width: 100%;
  }

  .loading {
    position: relative;
  }

  .empty-state {
    padding: 40px 0;
    text-align: center;
  }

  .card-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
  }

  .card-list.striped .card-item:nth-child(even) {
    background-color: #fafafa;
  }

  .card-item {
    border: 1px solid #ebeef5;
    background-color: #fff;
    transition: all 0.3s ease;
  }

  .card-item:hover {
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  }

  .card-header {
    padding: 12px 16px;
    border-bottom: 1px solid #ebeef5;
  }

  .card-content {
    padding: 12px;
  }

  .checkbox-column {
    flex-shrink: 0;
    margin-right: 8px;
  }

  .card-column {
    flex: 1;
    display: flex;
    align-items: center;
    margin-bottom: 4px;
  }

  .column-label {
    font-size: 14px;
    color: #999;
    margin-right: 8px;
  }

  .column-value {
    font-size: 14px;
    color: #303133;
  }

  .column-value.ellipsis {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .card-footer {
    padding: 12px 16px;
    border-top: 1px solid #ebeef5;
    text-align: right;
  }
</style>
